/**
 * @file singleLinkList.c
 * @author your name (you@domain.com)
 * @brief
 * @version 0.1
 * @date 2024-10-25
 *
 * @copyright Copyright (c) 2024
 *
 */
#include "stdint.h"
#include "string.h"
#include "stdlib.h"
#include "stdio.h"
#include "singleLinkList.h"

static void *memeryMalloc(int size)
{
    return malloc((size_t)size);
}

static void memeryFree(void *mem)
{
    free(mem);
}

node_t *appendHeadNode(node_t **head, int data)
{
    node_t *node_add = NULL;

    node_add = (node_t *)memeryMalloc(sizeof(node_t));
    if (node_add == NULL)
    {
        return node_add;
    }

    node_add->data = data;
    node_add->next = *head;
    *head = node_add;

    return node_add;
}

node_t *appendEndNode(node_t **head, int data)
{
    node_t *node_add = NULL;
    node_t *node_next = *head;

    node_add = (node_t *)memeryMalloc(sizeof(node_t));
    if (node_add == NULL)
    {
        return node_add;
    }
    node_add->data = data;
    node_add->next = NULL;

    if (*head == NULL)
    {
        *head = node_add;
        return node_add;
    }
    while (node_next->next)
    {
        node_next = node_next->next;
    }
    node_next->next = node_add;

    return node_add;
}

void modifiedNode(node_t *head, node_t *modified)
{
    node_t *node_modified = head;
    for (; node_modified; node_modified = node_modified->next)
    {
        if (node_modified == modified)
        {
            node_modified->data = modified->data;
            return;
        }
    }
}

node_t *queryNode(node_t *head, int data)
{
    node_t *node_query = head;
    for (; node_query; node_query = node_query->next)
    {
        if (node_query->data == data)
        {
            return node_query;
        }
    }

    return NULL;
}

int obtainNodeCount(node_t *head)
{
    int count = 0;
    node_t *node_count = head;
    for (; node_count; node_count = node_count->next)
    {
        count++;
    }
    return count;
}

void destroyHeadNode(node_t **head)
{
    node_t *delete_node = *head;

    if (delete_node)
    {
        *head = delete_node->next;
        memeryFree(delete_node);
    }
}

void destoryNode(node_t **head, node_t *node)
{
    for (node_t **cur = head; *cur;)
    {
        node_t *entry = *cur;
        if (entry == node)
        {
            *cur = entry->next;
            memeryFree(entry);
            return;
        }
        else
        {
            cur = &entry->next;
        }
    }
}

void destoryEndNode(node_t **head)
{
    node_t *delete_node = *head;

    if (delete_node == NULL)
    {
        return;
    }

    while (delete_node && delete_node->next != NULL)
    {
        delete_node = delete_node->next;
    }
    destoryNode(head, delete_node);
}

void destroyLinkList(node_t **head)
{
    int count = obtainNodeCount(*head);

    for (int i = 0; i < count; i++)
    {
        destroyHeadNode(head);
    }
}

void reverseLinkList(node_t **head)
{
    node_t *node_beg = NULL;
    node_t *node_end = NULL;

    if (*head == NULL || (*head)->next == NULL)
    {
        return;
    }

    node_beg = *head;
    node_end = node_beg->next;

    while (node_end)
    {
        node_beg->next = node_end->next;
        node_end->next = *head;
        *head = node_end;
        node_end = node_beg->next;
    }
}

node_t *reverseLinkListCom(node_t *head)
{
    node_t *node_beg = NULL;
    node_t *node_end = NULL;

    if (head == NULL || head->next == NULL)
    {
        return head;
    }

    node_beg = head;
    node_end = node_beg->next;

    while (node_end)
    {
        node_beg->next = node_end->next;
        node_end->next = head;
        head = node_end;
        node_end = node_beg->next;
    }

    return head;
}

node_t *recurseReverseLinkList(node_t *head)
{
    if ((head) == NULL || (head)->next == NULL)
    {
        return head;
    }

    node_t *new_node = recurseReverseLinkList(head->next);
    head->next->next = head;
    head->next = NULL;

    return new_node;
}


void destoryLinkListRecurse(node_t *head)
{
    if (head == NULL)
    {
        return;
    }

    destoryLinkListRecurse(head->next);
    free(head);
}



node_t *iterationReverseLinkList(node_t *head)
{
    if ((head) == NULL || (head)->next == NULL)
    {
        return head;
    }

    node_t *node_beg = NULL;
    node_t *node_mid = head;
    node_t *node_end = node_mid->next;

    while (1)
    {
        node_mid->next = node_beg;
        if (node_end == NULL)
        {
            break;
        }
        node_beg = node_mid;
        node_mid = node_end;
        node_end = node_end->next;
    }

    return node_mid;
}

void printLinkList(node_t *head)
{
    node_t *node_print = head;
    printf("start:\n");
    for (; node_print; node_print = node_print->next)
    {
        printf("node->data : %d\n", node_print->data);
    }
    printf("end\n");
}